/*
Nonlinear Input Editor
*/

import processing.xml.*;
import java.io.FileInputStream;
import java.io.FileOutputStream;
//import the ProControll Library
import procontroll.*;
import java.io.*;
// import UDP library (http://hypermedia.loeil.org/processing/)
import hypermedia.net.*;

ControllIO controll;
UDP udp;

String PROJECTNAME;

PImage[] icons;

int ACTIVELAYER = 0;
ArrayList layers;
ArrayList messages;

PFont font;
PImage blackLayer;

void setup()
{
  size(800,480);
  background(0);
  
  controll = ControllIO.getInstance(this);  //needs the applet instance
  udp = new UDP(this);
  
  PROJECTNAME = "newProject";
  
  icons = new PImage[50];
  icons[0]  = loadImage("icon_save.png");
  icons[1]  = loadImage("icon_open.png");
  icons[2]  = loadImage("icon_properties.png");
  icons[3]  = loadImage("icon_export.png");
  icons[4]  = loadImage("icon_trash.png");
  icons[5]  = loadImage("icon_new.png");
  icons[6]  = loadImage("icon_plus.png");
  icons[7]  = loadImage("ZoomIn.png");
  icons[8]  = loadImage("ZoomOut.png");
  icons[9]  = loadImage("icon_clear.png");
  icons[10] = loadImage("icon_autofit.png");
  icons[11] = new PImage(2,2);  //xbox controller
  icons[12] = new PImage(2,2);  //body rig
  icons[13] = icons[1];  //a repeat for the play layer
  icons[14] = loadImage("icon_play.png");
  icons[15] = loadImage("icon_pause.png");
  icons[16] = loadImage("icon_stop.png");
  icons[17] = loadImage("icon_seekLeft.png");
  icons[18] = loadImage("icon_seekRight.png");
  icons[19] = loadImage("icon_skipLeft.png");
  icons[20] = loadImage("icon_skipRight.png");
  icons[21] = new PImage(2,2);  //custom rig
  
  for(int i = 0; i < 4; i++)
  {
    icons[10].pixels[i] = color(0,0,0,0);
    icons[11].pixels[i] = color(0,0,0,0);
    icons[12].pixels[i] = color(0,0,0,0);
    icons[21].pixels[i] = color(0,0,0,0);
  }

  font = loadFont("font.vlw");
  textFont(font,20);
  
  blackLayer = new PImage(width,height);
  for(int i = 0; i < width*height; i++)
  {
    blackLayer.pixels[i] = color(255,255,255,48);  //gray out the background
  }
  
  layers = new ArrayList();
  messages = new ArrayList();
  
  layers.add(new MainLayer());
}

void draw()
{
 background(0);
 for(int i = 0; i < ACTIVELAYER+1; i++)
 {
   Layer lay = (Layer)layers.get(i);
   if(i == ACTIVELAYER)
   {
     if(lay.mDraw())
     {
       layers.remove(i);
       ACTIVELAYER--;
     }else{
       //see if this layer has any messages waiting for it in the queue
       for(int m = 0; m < messages.size(); m++)
       {
         Message mess = (Message)messages.get(m);
         if(mess.parent == i)
         {
           lay.mMessage(mess);            
           messages.remove(m);
           m--;           
         }
       }
     }
     //gray out the previous layers a bit...
     image(blackLayer,0,0);
   }
   image(lay.pg,lay.x,lay.y);
 }
}

int numPops = 0;

void keyReleased()
{
  Layer lay = (Layer)layers.get(ACTIVELAYER);
  lay.mKeyUp();  
}

void keyPressed()
{
  Layer lay = (Layer)layers.get(ACTIVELAYER);
  lay.mKeyDown();
  
  if (key == ESC) {
    key = 0;  //otherwise the app quits
    lay.mCancel();
  }

}

void mousePressed()
{
  Layer lay = (Layer)layers.get(ACTIVELAYER);
  if(mouseX > lay.x-5 && mouseX < lay.x+lay.w+5 && mouseY > lay.y-5 && mouseY < lay.y+lay.h+5) lay.mPress();  
}

void mouseReleased()
{
  Layer lay = (Layer)layers.get(ACTIVELAYER);
  lay.mRelease();
}

void mouseDragged()
{
  Layer lay = (Layer)layers.get(ACTIVELAYER);
  lay.mDrag();
}

/**********************************************
*  UDP STUFF (Tab removed to save space)
**********************************************/
//for now, I won't bother with Nils's signal filtering code... when it comes time to integrate with the 
//TUI3D Controllers I'll bundle it with the TUI3D controller code

//UDP Setup Code (31840 is arbitrary)
final int CHANNEL = 1;  
final int PORT = (31840 + CHANNEL);  
final String HOST = "localhost";

int LASTUPDATE;

void transmitUDP(boolean[] digital, int[] analog)
{
  //if no controller info is provided, assume we're only sending one controller
  transmitUDP(0,digital,analog);
}

void transmitUDP(int whichControl, boolean[] digital, int[] analog) {
  //I'll let each tab that uses the UDP functions (the live player and the play tab) create their
  //own functions for setting the digital/analog arrays
  
  String s = "";
  for(int i = 0; i < analog.length; i++)
  {
    s += analog[i] + " ";
  }
  //println(s);
  
  
  int digitalLength = constrain(digital.length, 0, 255);
  int analogLength = constrain(analog.length, 0, 255);
  
  byte[] datagram = new byte[3 + digitalLength + analogLength];
  //println("Datagram is... " + datagram.length);

  int index = 0;
  
  datagram[index++] = byte(whichControl);
  datagram[index++] = byte(digitalLength);
  datagram[index++] = byte(analogLength);
  
  //need to check later if we get a big performance boost by combining 
  //the boolean values into one byte per 8 instead of sending each as a separate byte
  for(int i = 0; i < digitalLength; i++) {
    datagram[index++] = byte( (digital[i] == true) ? 1 : 0 );
  }

  for(int i = 0; i < analogLength; i++) {
    datagram[index++] =  byte( constrain(analog[i], 0, 255) );
  }

  udp.send(datagram, HOST, PORT);
}
